package com.hd.trans.network.component

import android.os.Handler
import android.os.Looper
import android.text.TextUtils
import android.util.Log
import androidx.lifecycle.Lifecycle
import androidx.lifecycle.LifecycleObserver
import androidx.lifecycle.OnLifecycleEvent
import com.hd.trans.BuildConfig
import com.hd.trans.TranslationInterior
import com.hd.trans.common.Constants
import com.hd.trans.db.DataBaseMgr
import com.hd.trans.network.ApiServiceManager
import com.hd.trans.network.RxSchedulers
import com.hd.trans.network.apiService.UrlConstant
import com.hd.trans.network.bean.TaskResultRequest
import com.hd.trans.network.bean.TaskResultResponse
import com.hd.trans.network.bean.UserInfoBean
import com.hd.trans.network.bean.textToSpeech.Text2SpeechRequest
import com.hd.trans.network.bean.textToSpeech.Text2SpeechResponse
import com.hd.trans.network.bean.textToVoice.Text2VoiceRequest
import com.hd.trans.network.bean.textToVoice.Text2VoiceResponse
import com.hd.trans.share.DownloadArg
import com.hd.trans.share.UrlDownloadRequest
import com.hd.trans.ui.base.AppContextProvider
import com.hd.trans.ui.component.HdRecognitionComponent
import com.hd.trans.ui.component.RecognitionCallBack
import com.hd.trans.ui.service.NetDisposableObserver3
import com.hd.trans.utils.MediaFileUtil
import com.hd.trans.utils.StringUtils

/**
 * AI口语陪练封装管理类
 * 所用到的功能：
 * 1. 阿里语音识别
 * 2. AI通用聊天
 * 3. 文字转语音
 */
class AiSparringManager: AiSparringComponent, LifecycleObserver {
    private var tagId: String = ""
    private var splitSentenceList: MutableList<String>? = null
    private var isDestroy: Boolean = false
    var isTaskRunning: Boolean = false
    private var progress: Int = 0
    private var mAiSparingConfig: AiSparingConfig
    private var text2VoiceTaskId: String? = null
    private var text2VoiceContent: String? = null
    private val mHandler = Handler(Looper.getMainLooper())
    private var mAiSparringListener: SdkListener? = null
    private var mRecognitionComponent: HdRecognitionComponent
    private var mAiChatManager: AiChatManager
    //历史记录，软引用
    private var mHistoryList = arrayListOf<String>()

    /**
     * 页面销毁 终止回调
     */
    @OnLifecycleEvent(Lifecycle.Event.ON_DESTROY)
    fun destroy() {
        isDestroy = true
        onDestroy()
    }

    init {
        //测试用途
        val userinfoBean = if(BuildConfig.DEBUG){
            UserInfoBean(
                "DY1gO-KHJljWZUcDVBu78rKVywg52WArHICRZXHQStBXVO9K48p0rh7ip-4V0JtW5pJopEtNLLimBdh44rrTxh3tJQ",
                "o0j5B5wYZWlE2CXl-REscbRLdYl0",
                "",
                ""
            )
        }else{
            null
        }
        //默认配置
        mAiSparingConfig = AiSparingConfig.Builder()
            .setAiAnchor(AiAnchor.W3_720)
            .setUserInfoBean(userinfoBean)
//            .setAiSetting("你来自中国，你只会用中文回答")
//            .setTtsCode("Han")
            .setAiSetting("You are an AI speaking sparring assistant, you come to the UK and you will only answer in English")
            .setTtsCode("Shelley")
            .setPitch(1f)
            .setAliKey(DataBaseMgr.getInstance().getLanguageByTransCode("zh").aliAppKey)
            .setAiSparing(true)
            .setMediaType(MediaType.Audio)
            .setScreenWidth(480*2)
            .setScreenHeight(640*2)
            .build()

        mRecognitionComponent = HdRecognitionComponent(AppContextProvider.getContext(), false, 3000)
        mAiChatManager = AiChatManager()
    }

    fun setHistory(history: ArrayList<String>) {
        mHistoryList.clear()
        mHistoryList.addAll(history)
    }

    fun stopRecording(){
        mRecognitionComponent.stopRecognition()
    }

    fun onDestroy() {
        stopRecording()
        mHandler.removeCallbacksAndMessages(null)
    }

    enum class AiAnchor(val value: String) {
        M1_512("512-man-1"),
        M1_720("v720-man-1"),
        W3_512("512-woman-3"),
        W3_720("v720-woman-3"),
        W5_512("512-woman-5"),
        W5_720("v720-woman-5"),
        W1_0("1-woman-0"),
        W1_0_F18("1-woman-0-f18"),
    }
    enum class MediaType {
        Video,Audio
    }

    fun setAiSparringListener(listener: AiSparringListener?) {
        mAiSparringListener = listener
    }

    fun setAiSparingConfig(aiSparingConfig: AiSparingConfig){
        mAiSparingConfig = aiSparingConfig
    }

    fun getAiSparingConfig(): AiSparingConfig{
        return mAiSparingConfig
    }

    fun pauseRecording(){
        mRecognitionComponent.pauseRecording()
        onProgress("暂停录音",-1)
    }

    fun resumeRecording(){
        mRecognitionComponent.resumeRecording()
        onProgress("开始录音",-1)
    }

    private val mQueryText2VoiceRunnable: Runnable = object : Runnable {
        override fun run() {
            if(isDestroy){
                return
            }
            queryTaskResult(text2VoiceTaskId, queryAgain = {
                mHandler.removeCallbacks(this)
                mHandler.postDelayed(this, 2000)
            }){
                showLogDebug("text2Voice Url = ${it.video_url}")
                onProgress("",100)
                //解析私有地址
                onSuccess(text2VoiceContent?:"", it.video_url)
            }
        }
    }

    private fun showLogDebug(logMsg: String){
        if(TranslationInterior.isDebug())
            Log.d("AiSparringManager", logMsg)
    }

    fun startAiSparring() {
        if(!isTaskRunning){
            resumeRecording()
        }
        if(mRecognitionComponent.isStop){
            splitSentenceList?.clear()
            val aliAppKey = if(!mAiSparingConfig.lang.isNullOrEmpty()){
                DataBaseMgr.getInstance().getLanguageByTransCode(mAiSparingConfig.lang).aliAppKey
            }else{
                mAiSparingConfig.aliKey
            }
            mRecognitionComponent.voiceRecognition(aliAppKey,
                object : RecognitionCallBack {
                    override fun onRecognitionFailed(msg: String, code: Int) {
                        onFail(-1, "语音识别启动失败")
                    }

                    override fun onRecognitionCompleted(msg: String, code: Int) {
                    }

                    override fun onRecognitionChanged(
                        msg: String,
                        code: Int,
                        sentenceOver: Boolean,
                        sentence: String,
                    ) {
                        val content = sentence.trim()
                        if (TextUtils.isEmpty(content)) return
                        progress = 10
                        onProgress(content, progress)
                        if (sentenceOver && !isTaskRunning && mRecognitionComponent.isRecording()) {
                            showLogDebug("content = $content")
                            isTaskRunning = true
                            pauseRecording()
                            //AI对话---------------------------
                            if(mHistoryList.isNotEmpty() && mHistoryList.size > 0){
                                if(mHistoryList.size > 6){
                                    //最多保留6条
                                    val tempList = mHistoryList.subList(mHistoryList.size - 6, 6)
                                    mHistoryList.clear()
                                    mHistoryList.addAll(tempList)
                                }else if(mHistoryList.size%2 != 0){
                                    //确保是偶数
                                    mHistoryList.removeAt(0)
                                }
                            }
                            progress = 20
                            onProgress(content, progress)
                            if(mAiSparingConfig.isAiSparing){
                                chatWithAI(content)
                            }else{
                                //创建任务：文字转语音
                                createText2VoiceTask(content, true)
                            }
                            //---------------------------
                        }
                    }

                    override fun onVoiceChanged(waveBytes: Int, readBytes: Int) {
                    }
                })
        }
    }

    fun chatWithAI(question: String){
        isTaskRunning = true
        mAiChatManager.chatSSE(
            question,
            mAiSparingConfig.userInfoBean,
            mAiSparingConfig.aiSetting,
            mHistoryList,
            mAiSparingConfig.aiModel){
            if(it.code != 10000){
                onFail(it.code,it.message)
                return@chatSSE
            }
            if(it.output.isEmpty()){
                onFail(it.code,"AI识别失败")
                return@chatSSE
            }
            //创建任务：文字转语音
            createText2VoiceTask(it.output.trim(), true)
            //记录历史
            mHistoryList.add(question)
            mHistoryList.add(it.output)
        }
    }

    /**
     * 下载文件
     * @param downUrl 下载地址
     * @param savePath 保存路径（绝对路径），为空则保存到默认路径
     */
    private fun downloadFile(downUrl: String, savePath: String? = null) {
        val mediaFilePath = if(savePath.isNullOrEmpty()) {
            //解析私有地址
            val array = downUrl.split("?")
            val name = if (array.isEmpty()) {
                downUrl.substring(downUrl.lastIndexOf("/") + 1)
            }else{
                array[0].substring(array[0].lastIndexOf("/") + 1)
            }
            MediaFileUtil.getMediaDownloadPath() + name
        }else{
            savePath
        }
        //FileUtils.clearFolderSubFiles(File(videoFilePath).parentFile)// 删除缓存的文件
        val downloadThread = UrlDownloadRequest(null, downUrl, mediaFilePath)
        downloadThread.request(object : UrlDownloadRequest.DownloadCallback {
            override fun onDownloadStart(downloadArg: DownloadArg?) {
            }

            override fun onDownloadProgress(downloadArg: DownloadArg?, progress: Int) {
            }

            override fun onDownloadError(downloadArg: DownloadArg?) {
                onFail(-1, "下载失败")
            }

            override fun onDownloadComplete(downloadArg: DownloadArg?) {
                //下载完成
                showLogDebug("下载完成 Url = $mediaFilePath")
                onSuccess(text2VoiceContent?:"", mediaFilePath)
            }
        })
    }

    override fun queryTaskResult(task_id: String?, queryAgain: (() -> Unit)?, resultBack: ((TaskResultResponse) -> Unit)?) {
        if(task_id.isNullOrEmpty()) {
            return
        }
        ApiServiceManager.v4ApiService.queryTask(
            TaskResultRequest(task_id = task_id)
                .makeRequestBody(null))
            .compose(RxSchedulers.applySchedulers())
            .subscribe(NetDisposableObserver3(object :
                NetDisposableObserver3.NetCallBack<TaskResultResponse> {
                override fun onResponse(response: TaskResultResponse) {
                    when (response.code) {
                        10000 -> {
                            //任务处理成功,返回结果
                            resultBack?.invoke(response)
                        }
                        100602 -> {
                            //任务正在处理中,继续查询
                            queryAgain?.invoke()
                        }
                        101221 -> {
                            //文本合法性验证不通过
                            onFail(response.code, "AI回答内容的合法性验证不通过")
                        }
                        else -> {
                            onFail(response.code, response.message)
                        }
                    }
                }

                override fun onError(code: Int, msg: String) {
                    onFail(code, msg)
                }

                override fun onTokenInvalid(msg: String) {
                    onFail(-1, msg)
                }
            }))
    }

    private fun doNextTask(){
        showLogDebug("________________________________")
        if(splitSentenceList == null || splitSentenceList?.size == 0) return
        val text = splitSentenceList?.removeAt(0)
        showLogDebug("doNextTask = $text")
        if(mAiSparingConfig.engine == 1){
            textToVoice(text, mAiSparingConfig.ttsCode, mAiSparingConfig.pitch)
        }else if(mAiSparingConfig.engine == 2){
            textToSpeech(text, mAiSparingConfig.voice, mAiSparingConfig.type, mAiSparingConfig.lang)
        }
    }

    fun textToVoice(text: String?, lang: String, pitch: Float = 1f){
        isTaskRunning = true
        if(text == null || text.trim().isEmpty()){
            onFail(-1,"内容不能为空")
            return
        }
        if(lang == null || lang.trim().isEmpty()){
            onFail(-1,"语言不能为空")
            return
        }
        ApiServiceManager.v4ApiService.textToVoice(
            Text2VoiceRequest(
                text = text,
                lang = lang,
                pitch = pitch,
                type = "mp3")
                .makeRequestBody(mAiSparingConfig.userInfoBean))
            .compose(RxSchedulers.applySchedulers())
            .subscribe(NetDisposableObserver3(object :
                NetDisposableObserver3.NetCallBack<Text2VoiceResponse> {
                override fun onResponse(response: Text2VoiceResponse) {
                    if(response.code == 10000) { //任务创建成功
                        if(response.task_id.isEmpty()){
                            onFail(response.code,"文字转语音任务创建失败")
                            return
                        }
                        text2VoiceTaskId = response.task_id
                        text2VoiceContent = text
                        showLogDebug("text2VoiceTaskId = $text2VoiceTaskId")
                        mHandler.removeCallbacks(mQueryText2VoiceRunnable)
                        mHandler.post(mQueryText2VoiceRunnable)
                    }else{
                        onFail(response.code,response.message)
                    }
                }

                override fun onError(code: Int, msg: String) {
                    onFail(code, msg)
                }

                override fun onTokenInvalid(msg: String) {
                    onFail(-1, msg)
                }
            }))
    }

    fun textToSpeech(text: String?, voice: String, style: String, lang: String?){
        isTaskRunning = true
        if(text == null || text.trim().isEmpty()){
            onFail(-1,"内容不能为空")
            return
        }
        ApiServiceManager.ttsService.textToSpeech(
            Text2SpeechRequest(
                text = text,
                voice = voice,
                style = style,
                lang = lang)
                .makeRequestBody())
            .compose(RxSchedulers.applySchedulers())
            .subscribe(NetDisposableObserver3(object :
                NetDisposableObserver3.NetCallBack<Text2SpeechResponse> {
                override fun onResponse(response: Text2SpeechResponse) {
                    if(response.status) { //任务创建成功
                        if(response.url.isEmpty()){
                            onFail(Constants.ResponseCode.ERROR_COMM,"文字转语音任务创建失败")
                            return
                        }
                        val url = UrlConstant.getTtsUrl()+response.url
                        showLogDebug("text2Voice Url = $url")
                        onProgress("",100)
                        onSuccess(text, url)
                    }else{
                        onFail(Constants.ResponseCode.ERROR_COMM, response.reason?:"")
                    }
                }

                override fun onError(code: Int, msg: String) {
                    onFail(code, msg)
                }

                override fun onTokenInvalid(msg: String) {
                    onFail(-1, msg)
                }
            }))
    }

    override fun createText2VoiceTask(text: String, isAllowSplit: Boolean) {
        showLogDebug("text2Voice text = $text")
        progress = 30
        onProgress(text, progress)
        tagId = System.currentTimeMillis().toString()
        splitSentenceList?.clear()
        splitSentenceList = if(isAllowSplit){
            StringUtils.splitSentence(text)
        }else{
            ArrayList<String>().apply {
                add(text)
            }
        }
        if(splitSentenceList.isNullOrEmpty()){
            onFail(-1, "内容不能为空")
        }else{
            showLogDebug("splitSentenceList = ${splitSentenceList.toString()}")
            doNextTask()
        }
    }

    override fun createWav2LipTask(audio_url: String) {
    }

    private fun onFail(code: Int = -1, msg: String) {
        if(isDestroy){
            return
        }
        if(splitSentenceList == null || splitSentenceList?.size == 0){
            isTaskRunning = false
            resumeRecording()
            mHandler.post {
                mAiSparringListener?.onFail(code, msg)
            }
        }else{
            doNextTask()
        }
    }

    private fun onSuccess(msg: String, path: String) {
        if(isDestroy){
            return
        }

        if(splitSentenceList == null || splitSentenceList?.size == 0){
            isTaskRunning = false
        }else{
            doNextTask()
        }

        mHandler.post {
            mAiSparringListener?.onSuccess(tagId, msg, path)
        }
    }

    private fun onProgress(msg: String, progress: Int) {
        if(isDestroy){
            return
        }
        mHandler.post {
            mAiSparringListener?.onProgress(msg, progress)
        }
    }
}